-
-
Notifications
You must be signed in to change notification settings - Fork 888
Fix off-by-one errors when transforming images. #3011
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This pull request fixes off-by-one errors in image transformation operations by refactoring the coordinate space handling system. The changes remove the TransformSpace enum and consolidate all transformations to work in a consistent pixel space with proper normalization, improving accuracy in operations like rotation, skew, and projective transforms.
Key Changes
- Removed
TransformSpaceparameter from transformation APIs, simplifying the interface and ensuring consistent pixel-space operations - Introduced matrix normalization methods (
NormalizeToPixel) to correctly align transforms with pixel centers - Updated size calculation methods to use floating-point arithmetic for more accurate bounds computation
- Made struct methods
readonlyinPoint,PointF, andSizeFfor better performance and immutability
Reviewed Changes
Copilot reviewed 110 out of 110 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
src/ImageSharp/Processing/TransformSpace.cs |
Removed entire enum as coordinate space handling is now unified |
src/ImageSharp/Processing/Processors/Transforms/TransformUtils.cs |
Major refactoring of transformation utilities with new normalization and size calculation methods |
src/ImageSharp/Processing/AffineTransformBuilder.cs |
Removed TransformSpace parameter and related properties |
src/ImageSharp/Processing/ProjectiveTransformBuilder.cs |
Removed TransformSpace parameter and related properties |
src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor.cs |
Updated to use new canvas size calculation without transform space |
src/ImageSharp/Processing/Processors/Transforms/Linear/SkewProcessor.cs |
Updated to use new canvas size calculation without transform space |
src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs |
Added matrix normalization before inversion |
src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs |
Added matrix normalization before inversion |
src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs |
Updated to use new canvas size calculation methods |
src/ImageSharp/Primitives/Point.cs |
Added readonly modifier to methods for performance |
src/ImageSharp/Primitives/PointF.cs |
Added readonly modifier to methods for performance |
src/ImageSharp/Primitives/SizeF.cs |
Added readonly modifier to methods for performance |
src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs |
Updated subject area transformation to use floating-point rectangles |
tests/ImageSharp.Tests/TestImages.cs |
Added test image reference for Issue #3000 |
tests/ImageSharp.Tests/Processing/Transforms/TransformBuilderTestBase.cs |
Updated tests to remove TransformSpace parameter |
tests/ImageSharp.Tests/Processing/Processors/Transforms/RotateTests.cs |
Updated test assertions to reflect corrected transformation coordinates |
tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs |
Updated test assertions for subject area |
tests/ImageSharp.Tests/Processing/Processors/Transforms/ProjectiveTransformTests.cs |
Updated test assertions to reflect corrected transformation coordinates |
tests/ImageSharp.Tests/Processing/Processors/Transforms/AffineTransformTests.cs |
Added new test for Issue #3000 and updated existing tests |
| Multiple reference output images | Updated test reference images to reflect corrected transformation results |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Prerequisites
Description
A proper fix for #2753 and #3000
See #3000 (comment) for the explanation of the theory.
This pull request refactors several transformation and primitive classes to improve consistency, performance, and accuracy in image processing operations. The main changes include making value type members and methods
readonlyfor better immutability and optimization, removing unnecessary parameters related to transform space, and updating transformation logic to ensure correct coordinate space handling and more accurate results.Transformation Logic and API Simplification
TransformSpaceparameter and related properties fromAffineTransformBuilderand transformation utility methods, simplifying the API and ensuring all transformations are consistently defined in pixel space. (src/ImageSharp/Processing/AffineTransformBuilder.cs[1] [2] [3] [4] [5] [6] [7]RotateProcessor,SkewProcessor,AffineTransformProcessor,ProjectiveTransformProcessor) to use new utility methods for canvas size calculation and matrix normalization, ensuring correct sampling and output dimensions. (src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor.cs[1]src/ImageSharp/Processing/Processors/Transforms/Linear/SkewProcessor.cs[2] [3]src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs[4]src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs[5]src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs[1] [2]Value Type Improvements
Point,PointF, andSizeFstructsreadonly, which improves performance and thread safety by preventing modification of struct instances. (src/ImageSharp/Primitives/Point.cs[1] [2] [3]src/ImageSharp/Primitives/PointF.cs[4] [5] [6]src/ImageSharp/Primitives/SizeF.cs[7] [8]Rectangle and Area Transformation Accuracy
ExifProfile.SyncSubjectby switching from integer to floating-point rectangles for more accurate bounds calculation, and usingMathF.Floor/MathF.Ceilingfor coordinate rounding. (src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cssrc/ImageSharp/Metadata/Profiles/Exif/ExifProfile.csL343-R354)Documentation and Naming Consistency
src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cssrc/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.csL10-R11)Internal Utility Refactoring
src/ImageSharp/Processing/AffineTransformBuilder.cssrc/ImageSharp/Processing/AffineTransformBuilder.csL347-R351)